#include "registerDialog.h"
#include "Functionality/registerfactory.h"
#include "Functionality/registerfunctionality.h"
#include "qregularexpression.h"
#include "utils/util.h"

#include <QLabel>
#include <QRandomGenerator>
#include <QRegularExpressionValidator>
#include <QToolTip>

#include <QMessageBox>
#include <QPainter>
#include <bits/random.h>

registerDialog::registerDialog(QDialog *parent)
    : QDialog{parent}
    , mainLayout(new QVBoxLayout(this))
    , generator(rd())
    , passwdLineEditor1(new QLineEdit(this))
    , passwdLineEditor2(new QLineEdit(this))
    , phone(false)
    , passwd1(false)
    , passwd2(false)
    , code(false)
{
    mainLayout->setContentsMargins(10, 30, 10, 50);
    mainLayout->setSpacing(20);
    setMinimumSize(QSize(400, 500));
    setMaximumSize(QSize(400, 500));
    mainLayout->setAlignment(Qt::AlignCenter);

    QHBoxLayout *titleHLayout = new QHBoxLayout();
    titleHLayout->setObjectName("titleHLayout");
    titleHLayout->setAlignment(Qt::AlignCenter);

    QLabel *titleLabel = new QLabel(this);
    titleLabel->setObjectName("titleLabel");
    titleLabel->setText("新用户注册");
    QFont font = titleLabel->font();
    setQFont(font, "Microsoft YaHei", 16, false);
    titleLabel->setFont(font);
    titleHLayout->addWidget(titleLabel);

    mainLayout->addLayout(titleHLayout);

    //加上空白的空间
    QLabel *spaceLabel = new QLabel(this);
    spaceLabel->setObjectName("spaceLabel");
    spaceLabel->setMinimumSize(QSize(400, 10));
    spaceLabel->setMaximumSize(QSize(400, 10));
    mainLayout->addWidget(spaceLabel);
    //接着就是手机号了，直接复制前面的就行
    addPhoneLayout();

    passwdLineEditor1->setObjectName("passwdLineEditor1");
    passwdLineEditor2->setObjectName("passwdLineEditor2");
    addPasswdLayout(passwdLineEditor1, "密码");
    addPasswdLayout(passwdLineEditor2, "确认密码");
    addVerificationCode();

    addRegsiterBtn();

    factory = std::make_shared<registerFactory>(); //创建注册工厂
    //通过注册工厂来创建注册功能
    Functionality = factory->create(); //创建好了注册功能

    bindConnect();
}

void registerDialog::addPhoneLayout()
{
    QVBoxLayout *VLayout = new QVBoxLayout();
    VLayout->setSpacing(10);

    QHBoxLayout *HLayout = new QHBoxLayout();
    HLayout->setObjectName("HLayout");
    HLayout->setAlignment(Qt::AlignLeft);
    QLabel *labelPhone = new QLabel();
    setLable(labelPhone, "labelPhone", "手机号码", "Microsoft YaHei", 12);
    labelPhone->setStyleSheet("QLabel{color:black;}");
    HLayout->addWidget(labelPhone);
    VLayout->addLayout(HLayout);

    QHBoxLayout *HLayout2 = new QHBoxLayout();
    HLayout2->setAlignment(Qt::AlignLeft);
    HLayout2->setObjectName("HLayout2");
    HLayout2->setSpacing(6);
    QLabel *labelPhoneHeader = new QLabel();
    setLable(labelPhoneHeader, "labelPhoneHeader", "+86", "Microsoft YaHei", 10);
    HLayout2->addWidget(labelPhoneHeader);

    //这是设置竖线
    QFrame *line = new QFrame();
    line->setObjectName("line");
    line->setFrameShape(QFrame::VLine);
    line->setFrameShadow(QFrame::Raised);
    HLayout2->addWidget(line);

    //设置文本输入框
    phoneNumberlineEditor = new QLineEdit();
    phoneNumberlineEditor->setObjectName("phoneNumberlineEditor");
    phoneNumberlineEditor->setPlaceholderText("请输入手机号");
    phoneNumberlineEditor->setStyleSheet(
        "QLineEdit{border:none;border-bottom: 1px solid "
        "#cccccc;}QLineEdit:focus{border-bottom: 1px solid #0078d7;}");
    //安装输入验证器，使用正则表达式
    QRegularExpression regExp("^[0-9]+$");
    QRegularExpressionValidator *validator = new QRegularExpressionValidator(regExp, this);
    phoneNumberlineEditor->setValidator(validator);
    HLayout2->addWidget(phoneNumberlineEditor);

    VLayout->addLayout(HLayout2);
    mainLayout->addLayout(VLayout);
}

void registerDialog::addPasswdLayout(QLineEdit *passwdLineEditor, QString Text)
{
    QVBoxLayout *VLayout = new QVBoxLayout();
    VLayout->setSpacing(10);

    QHBoxLayout *HLayout = new QHBoxLayout();
    HLayout->setObjectName("HLayout");
    HLayout->setAlignment(Qt::AlignLeft);
    QLabel *labelPhone = new QLabel();
    setLable(labelPhone, "labelPhone", Text, "Microsoft YaHei", 12);
    labelPhone->setStyleSheet("QLabel{color:black;}");
    HLayout->addWidget(labelPhone);
    VLayout->addLayout(HLayout);

    QHBoxLayout *HLayout2 = new QHBoxLayout();
    HLayout2->setAlignment(Qt::AlignLeft);
    HLayout2->setObjectName("HLayout2");
    HLayout2->setSpacing(6);
    passwdLineEditor->setPlaceholderText("请输入密码");
    passwdLineEditor->setStyleSheet("QLineEdit{border:none;border-bottom: 1px solid "
                                    "#cccccc;}QLineEdit:focus{border-bottom: 1px solid #0078d7;}");
    //输入密码的需要设置回显模式
    passwdLineEditor->setEchoMode(QLineEdit::Password);

    HLayout2->addWidget(passwdLineEditor);
    VLayout->addLayout(HLayout2);
    mainLayout->addLayout(VLayout);
}

void registerDialog::addVerificationCode()
{
    QVBoxLayout *VLayout = new QVBoxLayout();
    VLayout->setSpacing(10);

    QHBoxLayout *HLayout = new QHBoxLayout();
    HLayout->setObjectName("HLayout");
    HLayout->setAlignment(Qt::AlignLeft);
    QLabel *labelPhone = new QLabel();
    setLable(labelPhone, "labelPhone", "验证码", "Microsoft YaHei", 12);
    labelPhone->setStyleSheet("QLabel{color:black;}");
    HLayout->addWidget(labelPhone);
    VLayout->addLayout(HLayout);

    HLayout2 = new QHBoxLayout();
    HLayout2->setAlignment(Qt::AlignLeft);
    HLayout2->setObjectName("HLayout2");
    HLayout2->setSpacing(6);
    verificationCodeLineEditor = new QLineEdit();
    verificationCodeLineEditor->setObjectName("passwdLineEditor");
    verificationCodeLineEditor->setPlaceholderText("请输入验证码");
    verificationCodeLineEditor->setStyleSheet(
        "QLineEdit{border:none;border-bottom: 1px solid "
        "#cccccc;}QLineEdit:focus{border-bottom: 1px solid #0078d7;}");

    HLayout2->addWidget(verificationCodeLineEditor);

    labelCode = new QLabel();
    labelCode->setObjectName("labelCode");
    QPixmap pixmap(QPixmap::fromImage(generateVerificationCode()));
    labelCode->setPixmap(pixmap);
    HLayout2->addWidget(labelCode);

    VLayout->addLayout(HLayout2);
    mainLayout->addLayout(VLayout);
}

QImage registerDialog::generateVerificationCode()
{
    const QString chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    //创建QImage对象
    QImage image(100, 50, QImage::Format_RGB32);
    //填充为白色
    image.fill(Qt::white);

    //使用画笔来画数据
    QPainter painter(&image);

    //开启抗锯齿
    painter.setRenderHint(QPainter::Antialiasing);
    //设置字体
    painter.setFont(QFont("Arial", 15, QFont::Bold));

    //生成六位数的随机验证码
    QString codeText;
    for (int i = 0; i < 6; ++i) {
        codeText += chars[randomValue()];
    }

    rawCodeText = codeText;
    //设置画笔的颜色
    QPen pen(Qt::red);
    painter.setPen(pen);

    painter.drawText(10, 30, codeText);

    pen = painter.pen();
    pen.setColor(Qt::black);
    painter.setPen(pen);
    // 添加干扰线
    for (int i = 0; i < 5; ++i) {
        int x1 = QRandomGenerator::global()->bounded(100);
        int y1 = QRandomGenerator::global()->bounded(50);
        int x2 = QRandomGenerator::global()->bounded(100);
        int y2 = QRandomGenerator::global()->bounded(50);
        painter.drawLine(x1, y1, x2, y2);
    }

    // 添加噪声（随机点）
    for (int i = 0; i < 100; ++i) {
        int x = QRandomGenerator::global()->bounded(100);
        int y = QRandomGenerator::global()->bounded(50);
        painter.drawPoint(x, y);
    }

    painter.end(); //这是结束绘制并提交到绘制的设备上去的。
    return image;
}

int registerDialog::randomValue()
{
    // std::random_device rd;        //随机种子
    // std::mt19937 generator(rd()); //使用rd初始化mt19937随机数生成器
    // std::uniform_int_distribution<> distribution(0, 51); //定义0-51的均匀分布
    return static_cast<int>(distribution(generator));
}

bool registerDialog::isValidPhoneNumber(const QString &phoneNumber)
{
    // 正则表达式：以1开头，第二位是3-9的数字，后面是9位数字，总共11位
    QRegularExpression regex("^1[3-9]\\d{9}$");
    return regex.match(phoneNumber).hasMatch();
}

void registerDialog::addRegsiterBtn()
{
    registerBtn = new QPushButton();
    setPushBtn(registerBtn,
               "loginBtn",
               QSize(360, 50),
               "",
               "border: none;",
               true,
               ":/resources/register.png");
    registerBtn->setEnabled(false);
    mainLayout->addWidget(registerBtn);
}

void registerDialog::bindConnect()
{
    connect(phoneNumberlineEditor, &QLineEdit::textEdited, [&](const QString &text) {
        if (!text.isEmpty()) {
            phone = true;
        } else
            phone = false;
        //然后需要判断四个
        if (phone && passwd1 && passwd2 && code) {
            registerBtn->setEnabled(true);
        } else
            registerBtn->setEnabled(false);
    });

    connect(passwdLineEditor1, &QLineEdit::textEdited, [&](const QString &text) {
        if (!text.isEmpty()) {
            passwd1 = true;
        } else
            passwd1 = false;
        //然后需要判断四个
        if (phone && passwd1 && passwd2 && code) {
            registerBtn->setEnabled(true);
        } else
            registerBtn->setEnabled(false);
    });

    connect(passwdLineEditor2, &QLineEdit::textEdited, [&](const QString &text) {
        if (!text.isEmpty()) {
            passwd2 = true;
        } else
            passwd2 = false;
        //然后需要判断四个
        if (phone && passwd1 && passwd2 && code) {
            registerBtn->setEnabled(true);
        } else
            registerBtn->setEnabled(false);
    });

    connect(verificationCodeLineEditor, &QLineEdit::textEdited, [&](const QString &text) {
        if (!text.isEmpty()) {
            code = true;
        } else
            code = false;
        //然后需要判断四个
        if (phone && passwd1 && passwd2 && code) {
            registerBtn->setEnabled(true);
        } else
            registerBtn->setEnabled(false);
    });

    connect(registerBtn, &QPushButton::clicked, this, &registerDialog::onRegisterBtnClicked);
    auto rf = dynamic_cast<registerFunctionality *>(Functionality.get());
    connect(rf,
            &registerFunctionality::registraSuccessed,
            this,
            &registerDialog::onregistraSuccessed);
    connect(rf, &registerFunctionality::registraFailed, this, &registerDialog::onregistraFailed);
}

void registerDialog::ResetVerificationCode()
{
    //重置验证码
    HLayout2->removeWidget(labelCode);

    QPixmap pixmap(QPixmap::fromImage(generateVerificationCode()));
    labelCode->setPixmap(pixmap);
    HLayout2->addWidget(labelCode);
}

void registerDialog::onRegisterBtnClicked()
{
    //获得所有的数据
    QString phoneNumber = phoneNumberlineEditor->text();
    QString passwd1 = passwdLineEditor1->text();
    QString passwd2 = passwdLineEditor2->text();
    QString code = verificationCodeLineEditor->text();

    if (!isValidPhoneNumber(phoneNumber)) {
        QRect rect = phoneNumberlineEditor->rect();
        QToolTip::showText(phoneNumberlineEditor->mapToGlobal(QPoint(0, 5)),
                           "手机号格式不正确",
                           phoneNumberlineEditor,
                           rect);
        return;
    }

    if (passwd1 != passwd2) {
        QRect rect = passwdLineEditor2->rect();
        QToolTip::showText(passwdLineEditor2->mapToGlobal(QPoint(0, 5)),
                           "两次密码不一致",
                           passwdLineEditor2,
                           rect);
        return;
    }

    if (code != rawCodeText) {
        QRect rect = verificationCodeLineEditor->rect();
        QToolTip::showText(verificationCodeLineEditor->mapToGlobal(QPoint(0, 5)),
                           "验证码错误",
                           verificationCodeLineEditor,
                           rect);
        ResetVerificationCode();
        return;
    }

    //下面就是需要封装好数据后，发送出去了
    // qDebug() << "发送数据";
    registerFunctionality *RF = dynamic_cast<registerFunctionality *>(Functionality.get());
    RF->setParameters(phoneNumber, passwd1);
    Functionality->executeFunction();
}

void registerDialog::onregistraSuccessed(QString data)
{
    QMessageBox::information(this, "提示", data);
}

void registerDialog::onregistraFailed(QString data)
{
    QMessageBox::critical(this,                 // 父窗口
                          "错误",               // 标题
                          data,                 // 错误内容
                          QMessageBox::Close,   // 按钮类型
                          QMessageBox::NoButton // 设置 "Cancel" 为默认按钮
    );

    // 处理用户的选择
    phoneNumberlineEditor->clear();
    passwdLineEditor1->clear();
    passwdLineEditor2->clear();
    verificationCodeLineEditor->clear();
    ResetVerificationCode();
}
